﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Kokomo.Environment
{
	/// <summary>
	/// Represents a document template.
	/// </summary>
	/// <remarks>
	/// See the remarks on <see cref="DelegatedDocumentTemplate"/> for
	/// instructions on providing document templates using composition.
	/// </remarks>
	public abstract class DocumentTemplate
	{
		/// <summary>
		/// The name of the <see cref="Title"/> property.
		/// </summary>
		/// <remarks>
		/// See the remarks on <see cref="DelegatedDocumentTemplate"/> for
		/// instructions on providing document templates using composition.
		/// </remarks>
		public const string TitlePropertyName = "Title";

		/// <summary>
		/// Initializes a new <see cref="DocumentTemplate"/> object.
		/// </summary>
		public DocumentTemplate()
		{
		}

		/// <summary>
		/// Gets the title of this template.
		/// </summary>
		public abstract UiString Title { get; }

		/// <summary>
		/// Instantiates a document using this template.
		/// </summary>
		/// <returns>An instance of <see cref="DocumentViewModel"/>, if a document is created; otherwise, <c>null</c>.</returns>
		/// <remarks>
		/// The implementation may display a UI
		/// to collect information from the user to build the document.
		/// If an error occurs during the creation of the <see cref="DocumentViewModel"/>,
		/// the implementation should throw an exception.
		/// It should only return <c>null</c> if the operation is canceled.
		/// </remarks>
		public abstract DocumentViewModel Instantiate();
	}

	public class DocumentTemplate<TDocument> : DocumentTemplate
		where TDocument : DocumentViewModel, new()
	{
		public DocumentTemplate(
			UiString title
			)
		{
			if (title == null) throw new ArgumentNullException("title");

			this._title = title;
		}

		private UiString _title;
		public override UiString Title
		{
			get { return this._title; }
		}

		public override DocumentViewModel Instantiate()
		{
			return new TDocument();
		}
	}
}
